<?php

/**
 * Created by Sven.
 * Date: 2016/12/26
 * Time: 23:47
 * 验证码类
 * 注意事项：
 * 1、背景的颜色 157 ~ 255 比较浅，字体的颜色 0 ~ 156 比较深
 */
class ValidateCode {

    private $charset = 'abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789';    //随机因子
    private $code = ''; // 验证码
    private $codeLen = 4; // 验证码长度
    private $img; // 图片资源
    private $width = 130; // 验证码长度
    private $height =  40; // 验证码宽度
    private $font;   // 字体路径
    private $fontSize; // 字体尺寸
    private $lineCount; // 线条数量
    private $dotCount; // 雪花数量
//    private $sessionKey; //  session中保存的键名

    public function __construct( $_config = array(
        'codeLen' => 4,
        'width' => 130,
        'height' => 40,
        'font' => ROOT_PATH.'/font/elephant.ttf',
        'fontSize' => 20,
        'lineCount' => 6,
        'dotCount' => 50
//        'sessionKey' => 'code'
    ) ) {

        if (isset($_config['codeLen'])){
            if ( is_numeric( $_config['codeLen'] ) ) {
                $_len = intval( $_config['codeLen'] );
                if ( $_len > 0 ) {
                    $this->codeLen = $_config['codeLen'];
                }
            } else {
                exit( 'ERROR: 非法的验证码长度' );
            }
        } else {
            $this->codeLen = 4;
        }

        if (isset($_config['width'])){
            if ($_config['width'] > 0){
                $this->width = intval($_config['width']);
            } else {
                exit( 'ERROR: 非法的验证码宽度'.$_config['width'] );
            }
        } else {
            $this->width = 130;
        }

        if (isset($_config['height'])){
            if ($_config['height'] > 0){
                $this->height = intval($_config['height']);
            } else {
                exit( 'ERROR: 非法的验证码高度'.$_config['height'] );
            }
        } else {
            $this->height = 130;
        }

        if (isset($_config['font'])){
            if (!empty($_config['font']) && file_exists($_config['font'])){
                $this->font = $_config['font'];
            } else {
                exit( 'ERROR: 验证码字体路径错误：'.$_config['font'] );
            }
        } else {
            $this->font = ROOT_PATH.'/font/elephant.ttf';
        }

        if (isset($_config['fontSize'])){
            if ($_config['fontSize'] > 10){
                $this->fontSize = intval($_config['fontSize']);
            } else {
                exit( 'ERROR: 验证码字体尺寸错误：'.$_config['fontSize'] );
            }
        } else {
            $this->fontSize = 20;
        }

        if (isset($_config['lineCount'])){
            if ($_config['lineCount'] > 0){
                $this->lineCount = intval($_config['lineCount']);
            } else {
                exit( 'ERROR: 验证码线条数量错误：'.$_config['lineCount'] );
            }
        } else {
            $this->lineCount = 6;
        }

        if (isset($_config['dotCount'])){
            if ($_config['dotCount'] > 0){
                $this->dotCount = intval($_config['dotCount']);
            } else {
                exit( 'ERROR: 验证码雪花数量错误：'.$_config['dotCount'] );
            }
        } else {
            $this->dotCount = 100;
        }

//        if (isset($_config['sessionKey']) && !empty($_config['sessionKey'])){
//            $this->sessionKey = $_config['sessionKey'];
//        } else {
//            $this->sessionKey = 'code';
//        }

    }

    //  创建随机码
    private function createCode() {
        $_charsetLen = strlen($this->charset) - 1;
        for ( $i = 0; $i < $this->codeLen; $i ++ ) {
            $this->code .= $this->charset[ mt_rand(0, $_charsetLen) ];
        }
        // 保存到session
//        session_start();
//        $_SESSION[$this->sessionKey] = $this->code;

    }

    // 创建背景
    private function createBg() {
        // 创建画布
        $this->img = imagecreate($this->width, $this->height);
        // 画矩形
        $_red = mt_rand(157, 255);
        $_green = mt_rand(157, 255);
        $_blue = mt_rand(157, 255);
        $_color = imagecolorallocate($this->img, $_red, $_green, $_blue);
        imagefilledrectangle($this->img, 0, $this->height, $this->width, 0, $_color);
    }

    private function createFont(){
        $_x = $this->width / $this->codeLen;
        for ($i = 0; $i < $this->codeLen; $i++){
            $_color = mt_rand(0, 156);
            imagettftext($this->img, mt_rand($this->fontSize - 5, $this->fontSize + 5),mt_rand(-30, 30), $_x * $i + mt_rand(1,5), $this->height / 1.5, $_color, $this->font, $this->code[$i] );
        }
    }

    private function createLine(){
        for ($i = 0; $i < $this->lineCount; $i++){
            $_red = mt_rand(0, 255);
            $_green = mt_rand(0, 255);
            $_blue = mt_rand(0, 255);
            $_color =  imagecolorallocate($this->img, $_red, $_green, $_blue);
            imageline($this->img, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $_color);
        }
    }

    private function createDot(){
        for ($i = 0; $i < $this->dotCount; $i++){
            $_red = mt_rand(0, 255);
            $_green = mt_rand(0, 255);
            $_blue = mt_rand(0, 255);
            $_color =  imagecolorallocate($this->img, $_red, $_green, $_blue);
            imagestring($this->img, mt_rand(1,5), mt_rand(0, $this->width), mt_rand(0, $this->height), '*', $_color);
        }
    }

    // 向浏览器输出
    private function outPut() {
        // 设置mimetype
        header('Content-Type:image/png');
        // 输出数据
        imagepng( $this->img);
        // 销毁资源
        imagedestroy($this->img);
    }

    /**
     * 创建、输出验证码
     */
    public function doImage() {
        //  创建随机码
        $this->createCode();
        // 创建背景资源
        $this->createBg();
        // 创建线条
        $this->createLine();
        // 创建雪花
        $this->createDot();
        // 创建字体
        $this->createFont();
        // 向浏览器输出
        $this->outPut();

    }

    /**
     * 获取生成的随机验证码
     * @return string 随机验证码
     */
    public function getCode(){
        if (empty($this->code)){
            exit('ERROR: getCode 方法必须在doImage之后调用');
        }

        return $this->code;
    }
}

